/**
 * 基于 LLM 的智能代码分析器
 * 用于更准确地分析依赖关系和 GN 文件配置
 */
import { LLMFactory } from '../../../../core/llm/llmFactory';
import { Logger } from '../../../../src/logger/Logger';
import { 
    DependencyAnalysisResult,
    GNAnalysisResult 
} from './MessageProtocol';

export class LLMAnalyzer {
    constructor(private llmFactory: LLMFactory) {}

    /**
     * 使用 LLM 智能分析代码依赖
     */
    async analyzeDependenciesWithLLM(
        sourceCode: string,
        fileName: string
    ): Promise<DependencyAnalysisResult> {
        Logger.info('[LLM Analyzer] 开始使用 LLM 分析依赖关系');
        
        const prompt = `你是一个专业的 C++ 代码分析专家。请分析以下 C++ 源代码的依赖关系。

## 源文件
文件名: ${fileName}

\`\`\`cpp
${sourceCode}
\`\`\`

## 分析要求
请以 JSON 格式返回分析结果，包含：

1. **includes**: 所有 #include 的头文件列表（字符串数组）
2. **externalDependencies**: 外部依赖列表，每个依赖包含：
   - name: 依赖名称（类名、函数名或库名）
   - type: 类型（"class" | "function" | "library"）
   - mockable: 是否可以 Mock（布尔值）
   - reason: 为什么需要这个依赖（简短说明）
3. **suggestions**: 测试建议列表（字符串数组），例如：
   - 是否需要 Mock 对象
   - 是否需要测试多线程场景
   - 是否需要测试异常处理
   - 其他测试相关建议

## 注意事项
- 只识别真正的外部依赖（不在当前文件定义的类和函数）
- 标准库的类（如 std::string）不算外部依赖
- 系统头文件（如 <iostream>）记录在 includes 中
- 第三方库（如 gmock、gtest）的类标记为可 Mock
- 分析代码中实际使用的类和函数，不只是看头文件

## 返回格式（纯 JSON，不要有任何额外说明）
\`\`\`json
{
  "includes": ["头文件1", "头文件2"],
  "externalDependencies": [
    {
      "name": "ClassName",
      "type": "class",
      "mockable": true,
      "reason": "在函数中创建了该类的实例"
    }
  ],
  "suggestions": [
    "建议1",
    "建议2"
  ]
}
\`\`\``;

        try {
            // 智能选择模型
            const { ModelSelector } = await import('../../../../core/llm/modelSelector');
            const selectedModel = ModelSelector.selectModel('general');
            
            let llm = this.llmFactory.getLLM(selectedModel);
            if (!llm) {
                const fallbackModels = ModelSelector.getFallbackModels('general');
                for (const fallbackModel of fallbackModels) {
                    llm = this.llmFactory.getLLM(fallbackModel);
                    if (llm) break;
                }
                if (!llm) {
                    throw new Error('无法获取 LLM 实例');
                }
            }

            let response = '';
            const abortController = new AbortController();
            const stream = llm._streamChat([
                { role: 'system', content: '你是一个专业的 C++ 代码分析助手，擅长分析代码依赖关系。' },
                { role: 'user', content: prompt }
            ], abortController.signal);

            for await (const chunk of stream) {
                if (chunk.content && typeof chunk.content === 'string') {
                    response += chunk.content;
                }
            }

            Logger.info(`[LLM Analyzer] LLM 响应长度: ${response.length}`);
            
            // 提取 JSON 内容
            const jsonMatch = response.match(/```json\s*([\s\S]*?)\s*```/) || 
                              response.match(/```\s*([\s\S]*?)\s*```/) ||
                              [null, response];
            
            const jsonContent = jsonMatch[1] || response;
            const result = JSON.parse(jsonContent.trim());

            Logger.info('[LLM Analyzer] 成功解析依赖分析结果');
            
            return {
                includes: result.includes || [],
                externalDependencies: (result.externalDependencies || []).map((dep: any) => ({
                    name: dep.name,
                    type: dep.type || 'class',
                    mockable: dep.mockable !== false,
                    reason: dep.reason
                })),
                suggestions: result.suggestions || []
            };

        } catch (error) {
            Logger.error(`[LLM Analyzer] 依赖分析失败: ${error}`);
            // 返回空结果而不是抛出错误，让调用方可以使用后备方案
            return {
                includes: [],
                externalDependencies: [],
                suggestions: ['LLM 分析失败，使用了基础解析']
            };
        }
    }

    /**
     * 使用 LLM 智能分析 GN 文件
     */
    async analyzeGNFileWithLLM(
        gnFilePath: string,
        gnContent: string,
        sourceFilePath: string
    ): Promise<GNAnalysisResult> {
        Logger.info('[LLM Analyzer] 开始使用 LLM 分析 GN 文件');
        
        const path = require('path');
        const sourceFileName = path.basename(sourceFilePath);
        const gnFileName = path.basename(gnFilePath);
        
        const prompt = `你是一个 OpenHarmony 构建系统专家，熟悉 GN (Generate Ninja) 构建配置。请分析以下 BUILD.gn 文件。

## GN 文件
文件路径: ${gnFilePath}

\`\`\`gn
${gnContent}
\`\`\`

## 分析目标
源文件: ${sourceFilePath}

## 分析要求
请以 JSON 格式返回分析结果，包含：

1. **testTargets**: 现有的测试目标列表，每个包含：
   - name: 目标名称
   - type: 目标类型（如 "ohos_unittest"）
   - sources: 测试源文件列表（如果能找到）
   
2. **recommendation**: 对于源文件 ${sourceFileName}，推荐的测试配置：
   - action: "add-to-existing" 或 "create-new"
   - targetName: 推荐的目标名称
   - testDirectory: 推荐的测试目录路径
   - reason: 推荐理由
   
3. **buildInfo**: 构建信息：
   - subsystem: 子系统名称（如果有）
   - part: 部件名称（如果有）
   - dependencies: 依赖的其他目标

## 注意事项
- OpenHarmony 项目通常使用 ohos_unittest 作为单元测试目标类型
- 测试文件通常在 test/ 或 unittest/ 目录下
- 如果已有测试目标，建议添加到现有目标；否则建议创建新目标
- 分析 sources = [...] 查看已有的测试文件

## 返回格式（纯 JSON，不要有任何额外说明）
\`\`\`json
{
  "testTargets": [
    {
      "name": "目标名称",
      "type": "ohos_unittest",
      "sources": ["test1.cpp", "test2.cpp"]
    }
  ],
  "recommendation": {
    "action": "add-to-existing",
    "targetName": "推荐的目标名",
    "testDirectory": "test/unittest",
    "reason": "推荐理由"
  },
  "buildInfo": {
    "subsystem": "子系统名",
    "part": "部件名",
    "dependencies": ["依赖1", "依赖2"]
  }
}
\`\`\``;

        try {
            // 智能选择模型
            const { ModelSelector } = await import('../../../../core/llm/modelSelector');
            const selectedModel = ModelSelector.selectModel('general');
            
            let llm = this.llmFactory.getLLM(selectedModel);
            if (!llm) {
                const fallbackModels = ModelSelector.getFallbackModels('general');
                for (const fallbackModel of fallbackModels) {
                    llm = this.llmFactory.getLLM(fallbackModel);
                    if (llm) break;
                }
                if (!llm) {
                    throw new Error('无法获取 LLM 实例');
                }
            }

            let response = '';
            const abortController = new AbortController();
            const stream = llm._streamChat([
                { role: 'system', content: '你是一个 OpenHarmony 构建系统专家，擅长分析 GN 构建配置。' },
                { role: 'user', content: prompt }
            ], abortController.signal);

            for await (const chunk of stream) {
                if (chunk.content && typeof chunk.content === 'string') {
                    response += chunk.content;
                }
            }

            Logger.info(`[LLM Analyzer] LLM 响应长度: ${response.length}`);
            
            // 提取 JSON 内容
            const jsonMatch = response.match(/```json\s*([\s\S]*?)\s*```/) || 
                              response.match(/```\s*([\s\S]*?)\s*```/) ||
                              [null, response];
            
            const jsonContent = jsonMatch[1] || response;
            const result = JSON.parse(jsonContent.trim());

            Logger.info('[LLM Analyzer] 成功解析 GN 分析结果');
            
            const gnDir = path.dirname(gnFilePath);
            
            return {
                gnFilePath,
                testTargets: (result.testTargets || []).map((target: any) => ({
                    name: target.name || 'unittest',
                    type: target.type || 'ohos_unittest',
                    sources: target.sources
                })),
                recommendation: {
                    action: result.recommendation?.action || 'add-to-existing',
                    targetName: result.recommendation?.targetName || 'unittest',
                    testDirectory: result.recommendation?.testDirectory 
                        ? path.join(gnDir, result.recommendation.testDirectory)
                        : path.join(gnDir, 'test'),
                    reason: result.recommendation?.reason
                },
                buildInfo: result.buildInfo
            };

        } catch (error) {
            Logger.error(`[LLM Analyzer] GN 分析失败: ${error}`);
            // 返回默认配置
            const gnDir = path.dirname(gnFilePath);
            return {
                gnFilePath,
                testTargets: [{
                    name: 'unittest',
                    type: 'ohos_unittest'
                }],
                recommendation: {
                    action: 'add-to-existing',
                    targetName: 'unittest',
                    testDirectory: path.join(gnDir, 'test'),
                    reason: 'LLM 分析失败，使用默认配置'
                }
            };
        }
    }

    /**
     * 使用 LLM 分析代码复杂度和测试建议
     */
    async analyzeTestStrategy(
        functionName: string,
        functionCode: string,
        dependencies: DependencyAnalysisResult
    ): Promise<{
        complexity: 'simple' | 'medium' | 'complex';
        testCases: string[];
        mockStrategy: string;
        additionalSuggestions: string[];
    }> {
        Logger.info('[LLM Analyzer] 分析测试策略');
        
        const prompt = `你是一个单元测试专家。请分析以下函数并提供测试策略建议。

## 函数代码
\`\`\`cpp
${functionCode}
\`\`\`

## 已识别的依赖
${JSON.stringify(dependencies, null, 2)}

## 分析要求
请以 JSON 格式返回：

1. **complexity**: 代码复杂度
   - "simple": 简单函数（无分支或1-2个分支，10行以内）
   - "medium": 中等复杂度（3-5个分支，10-30行）
   - "complex": 复杂函数（5个以上分支，或30行以上，或嵌套循环）

2. **testCases**: 推荐的测试用例列表（字符串数组），例如：
   - "正常情况：输入有效参数，验证返回值"
   - "边界条件：空值、零值、最大值"
   - "异常情况：无效参数、null 指针"

3. **mockStrategy**: Mock 策略建议（字符串）

4. **additionalSuggestions**: 额外测试建议（字符串数组）

## 返回格式（纯 JSON）
\`\`\`json
{
  "complexity": "medium",
  "testCases": ["测试用例1", "测试用例2"],
  "mockStrategy": "Mock 策略描述",
  "additionalSuggestions": ["建议1", "建议2"]
}
\`\`\``;

        try {
            // 智能选择模型
            const { ModelSelector } = await import('../../../../core/llm/modelSelector');
            const selectedModel = ModelSelector.selectModel('unitTest');
            
            let llm = this.llmFactory.getLLM(selectedModel);
            if (!llm) {
                const fallbackModels = ModelSelector.getFallbackModels('unitTest');
                for (const fallbackModel of fallbackModels) {
                    llm = this.llmFactory.getLLM(fallbackModel);
                    if (llm) break;
                }
                if (!llm) {
                    throw new Error('无法获取 LLM 实例');
                }
            }

            let response = '';
            const abortController = new AbortController();
            const stream = llm._streamChat([
                { role: 'system', content: '你是一个单元测试专家。' },
                { role: 'user', content: prompt }
            ], abortController.signal);

            for await (const chunk of stream) {
                if (chunk.content && typeof chunk.content === 'string') {
                    response += chunk.content;
                }
            }

            const jsonMatch = response.match(/```json\s*([\s\S]*?)\s*```/) || 
                              response.match(/```\s*([\s\S]*?)\s*```/) ||
                              [null, response];
            
            const jsonContent = jsonMatch[1] || response;
            const result = JSON.parse(jsonContent.trim());

            return {
                complexity: result.complexity || 'medium',
                testCases: result.testCases || [],
                mockStrategy: result.mockStrategy || '',
                additionalSuggestions: result.additionalSuggestions || []
            };

        } catch (error) {
            Logger.error(`[LLM Analyzer] 测试策略分析失败: ${error}`);
            return {
                complexity: 'medium',
                testCases: [],
                mockStrategy: '无法生成 Mock 策略',
                additionalSuggestions: []
            };
        }
    }
}

